-
Notifications
You must be signed in to change notification settings - Fork 357
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Additional annotation parsing #919
Additional annotation parsing #919
Conversation
Thanks @reicheratwork! Better to have a member in the corresponding nodes to indicate if something's optional so that each backend can use it. Also, would be nice to verify |
Can't @optional not be assigned to basic types as well? |
58415ce
to
ea54440
Compare
@k0ekk0ek in my most recent push, I added an idl_boolean_t is_optional to the idl_member_t class and created a utility function checking for this, so that the different backend implementations will not have to create their own |
a7b776c
to
979a3ad
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've reviewed these changes and found a few issues that need a fix, mainly the incomplete @default implementation and using the is_optional field instead of iterating through the annotations in idl_is_optional
. And some nit-picking on the consistency of the coding style.
src/idl/src/annotation.c
Outdated
idl_node_t *node) | ||
{ | ||
if (!idl_is_member(node) | ||
&& !idl_is_case(node)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In DDS XTypes spec section 7.2.2.4.4.4.7: "Union members, including the discriminator, shall never be optional", so I think that @optional should only be allowed on nodes of type idl_member_t
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is corrected in the new iteration.
src/idl/src/annotation.c
Outdated
if (annotation_appl->parameters | ||
&& annotation_appl->parameters->const_expr | ||
&& idl_mask(annotation_appl->parameters->const_expr) != (IDL_LITERAL | IDL_BOOL)) { | ||
idl_error(pstate, idl_location(annotation_appl), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit-pick: I'd prefer to have the indenting consistent with the rest of this file
src/idl/include/idl/tree.h
Outdated
@@ -299,6 +299,7 @@ struct idl_member { | |||
idl_declarator_t *declarators; | |||
/* metadata */ | |||
idl_boolean_t key; | |||
idl_boolean_t is_optional; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit-pick: is_key
and is_optional
or key
and optional
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are correct, in the newest iteration this is fixed.
However, some member names cannot be chosen as they are reserved keywords (such as default), so there I may need to use little workarounds.
"@optional cannot have non-boolean values assigned"); | ||
return IDL_RETCODE_SEMANTIC_ERROR; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't ((idl_member_t *)node)->is_optional
be set at this point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is no longer relevant, after rebasing I have changed to using the IDL_ANNOTATABLE macro
|
||
return IDL_RETCODE_OK; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} | ||
|
||
const idl_literal_t *idl_has_default(const void *node) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move to a separate PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the function name idl_has_default
I would expect a bool that indicates if the node has a default (which is what the function idl_is_default
below does). Maybe a better name would be idl_get_default_value
or something similar?
src/idl/src/tree.c
Outdated
|
||
if (lit | ||
&& idl_mask(lit) == (IDL_LITERAL | IDL_ANY)) | ||
return lit->value.bln; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this also work if an explicit default value 0
is applied to a member (@default(0)
), this function should return true in that case?
src/idl/tests/annotation.c
Outdated
|
||
idl_delete_pstate(pstate); | ||
|
||
const char *errstr[] = {"@optional stuct s {\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo stuct
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are correct.
src/idl/tests/annotation.c
Outdated
" e_2,\n" | ||
" e_3\n" | ||
"};\n"}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a test for invalid arguments, like @optional(1)
, @optional('true')
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The number of test cases will be expanded a lot in the next iteration.
src/idl/tests/annotation.c
Outdated
" @optional char c_default;\n" | ||
" @optional(true) char c_true;\n" | ||
" @optional char c_1_default, c_2_default;\n" | ||
"};\n"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add test some cases for other member types, e.g. aggregated types, sequences, arrays?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do.
Thanks for taking the time to look over this PR! I will take your comments into account, though I will probably rebase the current changes onto #923 when it has been merged into master. After which some of the new features' implementation may be quite different. |
The |
Super! |
eaabc51
to
44ddd02
Compare
src/idl/src/annotation.c
Outdated
if (!value || !idl_is_literal(value)) { | ||
idl_error(pstate, idl_location(annotation_appl), | ||
"@default requires a value"); | ||
return IDL_RETCODE_SEMANTIC_ERROR; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be an assert
. The parser checks the syntax and since there's no default, it should throw an error if there's no value specified. Probably good to add a small test for that (if there's none yet). If the test fails, we (or I) should fix the bug there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're correct that this should not really be checked here.
I will check whether the parser catches this, or if this requires a fix someplace else
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is correctly being checked by the parser at a previous step, and therefore I will replace this check with a simpler assert
src/idl/src/annotation.c
Outdated
//check whether type of literal matches type_spec of member | ||
switch(idl_mask(value)) { | ||
case IDL_LONG: | ||
if (!idl_is_integer_type(mem_spec)) { | ||
idl_error(pstate, idl_location(annotation_appl), | ||
"value type of @default does not match member"); | ||
return IDL_RETCODE_SEMANTIC_ERROR; | ||
} | ||
break; | ||
case IDL_DOUBLE: | ||
if (!idl_is_floating_pt_type(mem_spec)) { | ||
idl_error(pstate, idl_location(annotation_appl), | ||
"value type of @default does not match member"); | ||
return IDL_RETCODE_SEMANTIC_ERROR; | ||
} | ||
break; | ||
default: | ||
{ | ||
idl_mask_t value_type = (idl_mask(value) ^ IDL_LITERAL); | ||
if (idl_mask(mem_spec) != value_type) { | ||
idl_error(pstate, idl_location(annotation_appl), | ||
"value type of @default does not match member"); | ||
return IDL_RETCODE_SEMANTIC_ERROR; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This too, should have been done by the parser already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that there might be a misunderstanding here, this is checking whether the type in the literal (the parameter field of the @default
annotation) is compatible with that of the type it is being annotated to (so it should reject something like this: @default('a') long l;
src/idl/src/annotation.c
Outdated
if (idl_mask(const_expr) != (IDL_BOOL | IDL_LITERAL)) { | ||
idl_error(pstate, idl_location(annotation_appl), | ||
"@optional cannot have non-boolean values assigned"); | ||
return IDL_RETCODE_SEMANTIC_ERROR; | ||
} else { | ||
value = ((const idl_literal_t*)const_expr)->value.bln; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably checked by the parser already. Like in one of my earlier comments, let's add a couple of small tests and fix the parser if it doesn't behave correctly already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're correct that this should not really be checked here.
I will check whether the parser catches this, or if this requires a fix someplace else
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is correctly being checked by the parser at a previous step, and therefore I will replace this check with a simpler assert
src/idl/src/annotation.c
Outdated
idl_error(pstate, idl_location(annotation_appl), | ||
"@default_literal can only be assigned to member nodes"); | ||
return IDL_RETCODE_SEMANTIC_ERROR; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will be fixed
src/idl/include/idl/tree.h
Outdated
@@ -378,6 +380,7 @@ struct idl_enumerator { | |||
mapped to a native data type capable of representing a maximally-sized | |||
enumeration */ | |||
IDL_ANNOTATABLE(uint32_t) value; | |||
IDL_ANNOTATABLE(bool) is_default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In closing the enum
declaration we should check if there's only one default. Plus, I'm thinking it may actually make more sense to have a default_enumerator
member in the enum
too/instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default_enumerator
could then point to the first enumerator is not explicit default is provided? (Probably works like that, but I'm not a 100% sure)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe introduce IDL_DEFAULT_ENUMERATOR
that equals IDL_ENUMERATOR | 1u
. The (implicit) default case for unions works like that as well. Don't know if it makes sense, but it might be worth looking into that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My attempt here was to modify the existing interface as little as possible, but your approach should result in less duplicated functionality, as the different backends will not have to implement their own checks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will look into the default member approach
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to a default_enumerator pointer in the idl_enum class
src/idl/tests/annotation.c
Outdated
{IDL_RETCODE_ILLEGAL_EXPRESSION, false, "struct s { @optional(\"true\") char c; };" }, | ||
{IDL_RETCODE_ILLEGAL_EXPRESSION, false, "struct s { @optional(123) char c; };" }, | ||
{IDL_RETCODE_ILLEGAL_EXPRESSION, false, "struct s { @optional(0.1) char c; };" }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it'd be nicer to cover these in more generic annotation tests(?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My reasoning behind putting the tests for the correct parameter type in the annotation is that this is something that is unique to the @optional annotation, and in my opinion, having a whole forest of different checks of matching the parameter type with the annotation type would be less descriptive.
src/idl/tests/annotation.c
Outdated
{IDL_RETCODE_ILLEGAL_EXPRESSION, false, "struct s { @optional(123) char c; };" }, | ||
{IDL_RETCODE_ILLEGAL_EXPRESSION, false, "struct s { @optional(0.1) char c; };" }, | ||
{IDL_RETCODE_SEMANTIC_ERROR, false, "enum e { e_0, @optional e_1};" }, | ||
{IDL_RETCODE_SYNTAX_ERROR, false, "union u switch (long) { case 0: @optional double d; };"} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same for this one because we're actually testing the syntax rather than something @optional
specific.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same reasoning as previous comment.
990ef0c
to
be6348e
Compare
be6348e
to
909dd8c
Compare
/* skipping this test as idl_create_annotation_appl leaks memory if idl_resolve cannot resolve the scoped name (https://github.com/eclipse-cyclonedds/cyclonedds/issues/950) | ||
{"@default(e_0) enum e { e_0, e_1, e_2, e_3 };", IDL_RETCODE_SEMANTIC_ERROR, false, IDL_NULL, NULL} //setting default on enums is done through @default_literal | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better enable this and indicate the test is known to fail using the WILL_FAIL property. Then, when the fix for #950 is in, the test will pass (causing the build to fail). The advantage being that we're actively notified when a change is required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The issue is not here that the test fails, it is that there is a memory leak that is triggered by this test, and that the builds in Azure that check for memory leaks will fail if this test is done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know, but CTest will mark it as a failure. Since WILL_FAIL
is a CTest property, it'll get us the desired behavior right? If you prefer you may set the test to disabled. It's just that commenting it out only ensures it's never looked after again. At least, there's tons of commented out tests (or test ideas) for libidl that would've caught a bunch of things but they were never looked at or thought of again... I prefer to have some kind of notification that something is still off, at least that way no one forgets.
src/idl/tests/annotation.c
Outdated
} | ||
} | ||
|
||
CU_Test(idl_annotation, enum_default) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you can find the time, please rename the testcase to default_literal
. That way it's directly obvious in the logs/terminal what this test is meant to test (not that it's super hard to guess, but still).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do.
- The parser was not proceeding correctly in the case of the state being IDL_SCAN_ANNOTATION_APPL_SCOPED_NAME Signed-off-by: Martijn Reicher <martijn.reicher@adlinktech.com>
- The parser was setting the node mask to IDL_ANY in stead of the correct mask for bool, char and string literals Signed-off-by: Martijn Reicher <martijn.reicher@adlinktech.com>
- Reject @optional annotations on anything other than members - Reject mixing @key and @optional fields - Add idl_is_optional function which checks for the @optional annotation for idl_members and idl_declarators on members - Add unittests for @optional field parsing Signed-off-by: Martijn Reicher <martijn.reicher@adlinktech.com>
909dd8c
to
1163532
Compare
Just a couple of warnings in the tests, if those are solved, I'll happily merge |
That one escaped my notice, I will fix it immediately. |
- Add parsing of @default annotation fields - Reject mixing @default and @optional fields - Add idl_has_default function returns a pointer to the idl_literal_t representing the default value assigned to the node, or NULL if there is none - Add unittests for @default annotation Signed-off-by: Martijn Reicher <martijn.reicher@adlinktech.com>
- Set trough the @default_literal annotation on enumerators - Add the default_enumerator pointer in idl_enum, which is set to the enumerator with @default_literal annotation or the first if none have the annotation - Add unittests Signed-off-by: Martijn Reicher <martijn.reicher@adlinktech.com>
1163532
to
010289e
Compare
Signed-off-by: Martijn Reicher martijn.reicher@adlinktech.com